
#include <BKeyEvent>
#include <BMouseEvent>
#include <BCamera>
#include <BViewer>
#include <BHandler>
#include "member_BHandler.h"
#include "member_BCamera.h"
#include "member_BObject.h"

using namespace BWE;

#define member					(*(member_BHandler*)_ptr)
#define member_allocate()		_ptr = new member_BHandler(this)
#define member_release()		delete (member_BHandler*)_ptr

BHandler::BHandler(BHandler* parent) : BObject()
{
	member_allocate();
	if (parent)
		parent->addChild(this);
}
BHandler::BHandler(const BString& name, BHandler* parent) : BObject(name)
{
	member_allocate();
	if (parent)
		parent->addChild(this);
}
BHandler::~BHandler()
{
	for (int i = 0; i < member.children.size(); i++)
	{
		BHandler* child = member.children[i];
		handler_member(child)->parent = 0;
	}
	member_release();
}

BViewer* BHandler::viewer() const
{
	return member.viewer;
}
BCamera* BHandler::camera() const
{
	BCamera* camera = 0;
	if (member.viewer)
		camera = member.viewer->camera();
	return camera;
}
BScene* BHandler::scene() const
{
	if (member.viewer)
	{
		return member.viewer->scene();
	}
	return 0;
}
bool BHandler::fresh() const
{
	if (member.viewer)
	{
		member.viewer->fresh();
		if (BCamera* camera = member.viewer->camera())
		{
			camera->fresh();
		}
		return true;
	}
	return false;
}

void BHandler::setParent(BHandler* parent)
{
	if (member.parent != parent && parent != this)
	{
		BHolder<BHandler> holder;
		if (member.parent)
		{
			holder = this;
			member.parent->removeChild(this);
		}
		if (parent)
		{
			parent->addChild(this);
			holder = 0;
		}
	}
}
const BHandler* BHandler::parent() const
{
	return member.parent;
}
BHandler* BHandler::parent()
{
	return member.parent;
}

void BHandler::addChild(BHandler* child)
{
	if (!child || child == this)
		return;
	if (handler_member(child)->parent == this)
		return;
	if (member.children.append(child))
	{
		if (BHandler* parent = handler_member(child)->parent)
			parent->removeChild(child);
		handler_member(child)->parent = this;
		handler_member(child)->setViewer(member.viewer);
		object_member(child)->emit(Signal_ParentChanged, BValue(this, true));
		this->emit(Signal_Insert, BValue(child, this));
		this->fresh();
	}
}
void BHandler::insertChild(int pos, BHandler* child)
{
	if (!child || child == this)
		return;
	if (handler_member(child)->parent == this)
		return;
	int index = member.children.find(child);
	if (index < member.children.size())
	{
		member.children.move(index, pos);
		return;
	}
	member.children.insert(pos, child);
	if (BHandler* parent = handler_member(child)->parent)
		parent->removeChild(child);
	handler_member(child)->parent = this;
	handler_member(child)->setViewer(member.viewer);
	object_member(child)->emit(Signal_ParentChanged, BValue(this, true));
	this->emit(Signal_Insert, BValue(child, this));
	this->fresh();
}
void BHandler::removeChild(BHandler* child)
{
	if (child && child != this && handler_member(child)->parent == this)
	{
		BHolder<BHandler> holder(child);
		handler_member(child)->parent = 0;
		handler_member(child)->setViewer(0);
		member.children.remove(child);
		object_member(child)->emit(Signal_ParentChanged);
		this->emit(Signal_Remove, BValue(child, this));
		this->fresh();
	}
}
void BHandler::clearChildren()
{
	while (BHandlerHolder child = member.children.last())
	{
		this->removeChild(child);
	}
}

bool BHandler::contain(BHandler* child)
{
	return member.children.contain(child);
}
bool BHandler::contain(const BString& name) const
{
	for (int i = 0; i < member.children.size(); i++)
	{
		if (member.children[i]->name() == name)
			return true;
	}
	return false;
}

int BHandler::childCount() const
{
	return member.children.size();
}
BHandler* BHandler::child(int index) const
{
	return member.children(index);
}
BHandler* BHandler::child(const BString& name) const
{
	for (int i = 0; i < member.children.size(); i++)
	{
		if (member.children[i]->name() == name)
			return member.children[i];
	}
	return 0;
}

int BHandler::index() const
{
	if (BHandler* parent = member.parent)
	{
		BArray<BHandlerHolder>& children = handler_member(parent)->children;
		return children.find(this);
	}
	return -1;
}
bool BHandler::above(const BHandler* other) const
{
	if (!other)
		return false;
	BHandler* parent = handler_member(other)->parent;
	while (parent)
	{
		if (parent == this)
			return true;
		parent = handler_member(parent)->parent;
	}
	return false;
}
bool BHandler::under(const BHandler* other) const
{
	BHandler* parent = member.parent;
	while (parent)
	{
		if (parent == other)
			return true;
		parent = handler_member(parent)->parent;
	}
	return false;
}

void BHandler::raise()
{
	if (member.parent)
	{
		BArray<BHandlerHolder>& children = handler_member(member.parent)->children;
		int pos = children.find(this);
		children.move(pos, 0);
		this->fresh();
	}
}
void BHandler::lower()
{
	if (member.parent)
	{
		BArray<BHandlerHolder>& children = handler_member(member.parent)->children;
		int pos = children.find(this);
		children.move(pos, children.size() - 1);
		this->fresh();
	}
}
bool BHandler::detach()
{
	if (member.parent)
	{
		member.parent->removeChild(this);
		return true;
	}
	if (member.viewer)
	{
		member.viewer->setHandler(0);
		return true;
	}
	return false;
}

void BHandler::attached(BViewer* viewer)
{

}
void BHandler::detached(BViewer* viewer)
{

}

void BHandler::paint(BPainter& painter)
{

}
void BHandler::render(BRender& render)
{

}
void BHandler::event(const BEvent& event)
{
	if (!member.viewer)
		return;

	for (int i = member.children.size() - 1; i >= 0; i--)
	{
		BHandler* child = member.children[i];
		if (!child->enabled())
			continue;
		child->event(event);
		if (event.accepted())
			return;
	}

	switch (event.type())
	{
	case Event_Update:
		this->updateEvent(event);
		break;
	case Event_Style:
		this->styleEvent(event);
		break;
	case Event_Fresh:
		this->freshEvent(event);
		break;
	case Event_Focus:
		this->focusEvent(event);
		break;
	case Event_Move:
		this->moveEvent(event);
		break;
	case Event_Resize:
		this->resizeEvent(event);
		break;
	case Event_KeyPress:
		this->keyPressEvent((const BKeyEvent&)event);
		break;
	case Event_KeyRelease:
		this->keyReleaseEvent((const BKeyEvent&)event);
		break;
	case Event_MouseEnter:
		this->mouseEnterEvent((const BMouseEvent&)event);
		break;
	case Event_MouseLeave:
		this->mouseLeaveEvent((const BMouseEvent&)event);
		break;
	case Event_MouseMove:
		this->mouseMoveEvent((const BMouseEvent&)event);
		break;
	case Event_MousePress:
		this->mousePressEvent((const BMouseEvent&)event);
		break;
	case Event_MouseRelease:
		this->mouseReleaseEvent((const BMouseEvent&)event);
		break;
	case Event_MouseClick:
		this->mouseClickEvent((const BMouseEvent&)event);
		break;
	case Event_DoubleClick:
		this->mouseDoubleClickEvent((const BMouseEvent&)event);
		break;
	case Event_MouseWheel:
		this->mouseWheelEvent((const BMouseEvent&)event);
		break;
	case Event_DragEnter:
		this->dragEnterEvent((const BMouseEvent&)event);
		break;
	case Event_DragLeave:
		this->dragLeaveEvent((const BMouseEvent&)event);
		break;
	case Event_DragMove:
		this->dragMoveEvent((const BMouseEvent&)event);
		break;
	case Event_DragDrop:
		this->dragDropEvent((const BMouseEvent&)event);
		break;
	default:
		break;
	}
}

void BHandler::updateEvent(const BEvent& event)
{

}
void BHandler::styleEvent(const BEvent& event)
{

}
void BHandler::freshEvent(const BEvent& event)
{

}

void BHandler::moveEvent(const BEvent& event)
{

}
void BHandler::resizeEvent(const BEvent& event)
{

}

void BHandler::focusEvent(const BEvent& event)
{

}
void BHandler::keyPressEvent(const BKeyEvent& keyEvent)
{

}
void BHandler::keyReleaseEvent(const BKeyEvent& keyEvent)
{

}

void BHandler::mouseEnterEvent(const BMouseEvent& mouseEvent)
{

}
void BHandler::mouseLeaveEvent(const BMouseEvent& mouseEvent)
{

}

void BHandler::mousePressEvent(const BMouseEvent& mouseEvent)
{

}
void BHandler::mouseReleaseEvent(const BMouseEvent& mouseEvent)
{

}
void BHandler::mouseMoveEvent(const BMouseEvent& mouseEvent)
{

}
void BHandler::mouseWheelEvent(const BMouseEvent& mouseEvent)
{

}

void BHandler::mouseClickEvent(const BMouseEvent& mouseEvent)
{

}
void BHandler::mouseDoubleClickEvent(const BMouseEvent& mouseEvent)
{

}

void BHandler::dragEnterEvent(const BMouseEvent& mouseEvent)
{

}
void BHandler::dragLeaveEvent(const BMouseEvent& mouseEvent)
{

}
void BHandler::dragMoveEvent(const BMouseEvent& mouseEvent)
{

}
void BHandler::dragDropEvent(const BMouseEvent& mouseEvent)
{

}

